package org.jugile.jsontmpl.domain;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.jugile.jsontmpl.common.*;
import org.jugile.util.Node;
import org.jugile.util.Vo;

public class Array2 extends Array2Base implements org.jugile.util.IDO {

	public Value createValue() {
		return d().createValue().setItemArray2(this);
	}

	public List<Value> getValuesSorted() {
		return getItemValues().sort("id");
	}
	public Value getFirstValue() {
		return getItemValues().first("id");
	}

	public Node toXml() {
		Node n = new Node(FldType.ARRAY.getLabel());
		for (Value v : getValuesSorted()) n.add(v.toXml());
		return n;
	}
	public Object toVo(int idx) {
		List l = new ArrayList();
		for (Value v : getValuesSorted()) l.add(v.toVo(idx));
		return l;
	}
	
	public Object toVo(EvalCtx ctx) {
		Object coll = ctx.model();
		if (coll == null) return null;
		Value val = getFirstValue();
		if (val == null) fail("list does not have example item: " + getFldName());
		List l = new ArrayList();
		if (coll instanceof Iterable) {
			Iterable items = (Iterable)coll;
			for (Object o : items) {
				ctx.push(o);
				Object v = val.toVo(ctx);
				ctx.pop();
				if (v != null) l.add(v); // only non null items added
			}
		} else {
			fail("not iterable object for list: " + getFldName());
		}
		return l;
	}
	
	public String getFldName() {
		Value binding = getValues().unique();
		if (binding == null) return null;
		Fld fld = binding.getFld();
		if (fld == null) return null;
		return fld.getName();
	}
	
	public Array2 parse(Ctx ctx, Node n) {
		n.validateElements("desc obj list str bool num ts");
		if (!FldType.ARRAY.getLabel().equals(n.name())) fail("expected list element");
		for (Node v : n.children()) {
			if (d().getFldType(v.name()) != null) 
				createValue().parse(ctx, v);
		}
		return this;
	}

	public void onDelete() {
		for (Value v : getItemValues()) v.delete();
	}
	
}